// src 用于读取文件流  
// dest 用于写入文件流
// parallel 用于并行执行任务（同时执行）
// series 用于串行执行任务（一个一个按顺序执行）
// watch 用于监听文件修改
const {src, dest, parallel, series, watch} = require('gulp')

// del 模块用来清理文件
const del = require('del')

// browserSync 模块用来创建一个静态服务器， 结合 gulp 的 watch 任务实现即时编译浏览器即时刷新
const browserSync = require('browser-sync')
const bs = browserSync.create()

// gulp-load-plugins 模块用来自动加载gulp插件
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()

// 模板html文件需要的数据
const data = {
    menus: [
        {
            name: "Home",
            icon: "aperture",
            link: "index.html",
        },
        {
            name: "Features",
            link: "features.html",
        },
        {
            name: "About",
            link: "about.html",
        },
        {
            name: "Contact",
            link: "#",
            children: [
                {
                    name: "Twitter",
                    link: "https://twitter.com/w_zce",
                },
                {
                    name: "About",
                    link: "https://weibo.com/zceme",
                },
                {
                    name: "divider",
                },
                {
                    name: "About",
                    link: "https://github.com/zce",
                },
            ],
        },
    ],
    pkg: require("./package.json"),
    date: new Date(),
};
// clean 任务 用于清除打包构建生成的dist目录 和 产生的临时目录 temp
const clean = () => {
    return del(['dist', 'temp'])
}
// style 任务  用于编译css
// 编译完成之后拷贝文件至临时目录temp，使用 bs.reload 通知浏览器自动刷新
const style = () => {
    return src('src/assets/styles/*.scss', { base: 'src'} )
        .pipe(plugins.sass({
             outputStyle: 'expanded'
        }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}))
}
// script 任务  用于结合babel编译js
// 编译完成之后拷贝文件至临时目录temp，使用 bs.reload 通知浏览器自动刷新
const script = () => {
    return src('src/assets/scripts/*.js', {base: 'src'})
        .pipe(plugins.babel({
            presets: ['@babel/preset-env']
        }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}))
}
// page 任务  用于通过模板引擎swig结合data数据编译html
// 编译完成之后拷贝文件至临时目录temp，使用 bs.reload 通知浏览器自动刷新
const page = () => {
    return src('src/*.html', {base: 'src'})
        .pipe(plugins.swig({
            data,
            defaults: { cache: false } // 防止模板缓存导致页面不能及时更新
        }))
        .pipe(dest('temp'))
        .pipe(bs.reload({ stream: true}))
}
// image 任务  用于压缩图片，拷贝图片至dist目录
const image = () => {
    return src('src/assets/images/**', {base: 'src'})
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
// image 任务  用于压缩svg字体，拷贝字体至dist目录
const font = () => {
    return src('src/assets/fonts/**', {base: 'src'})
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
// extra 任务  用于拷贝 public 夹下的所有文件（public下放的都是静态文件）至dist目录
const extra = () => {
    return src('public/**', {base: 'public'})
        .pipe(dest('dist'))
}

// hotServer 任务 用于开启一个静态服务器，结合 gulp 的 watch 任务实现即时编译和自动更新
const hotServer = () => {
    watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)

    watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
    ], bs.reload)

    bs.init({
        notify: false,
        port: 2080,
        open: true,
        // files: 'dist/**',
        server: {
            baseDir: ['temp', 'src', 'public'],
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    })
}

// useref 用于处理 html 中引用的资源 ， 比如   <link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
// 同时在这个过程中，通过 gulp 的压缩插件对文件进行压缩处理，输出至 dist 目录
const useref = () => {
    return src('temp/*.html', { base: 'temp' })
        .pipe(plugins.useref({ searchPath: ['temp', '.']}))
        // html js css
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true
        })))
        .pipe(dest('dist'))
}  

const compile = parallel(style, script, page)

// 生产任务
const build = series(clean, 
    parallel(
        series(compile, useref), 
        image, 
        font, 
        extra)
)
// 开发任务
const serve = parallel(compile, hotServer)

module.exports = {
    clean,
    build,
    serve
}